package config

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/meta"
	"code.bydev.io/frameworks/sechub-go/api"
	sechub_client "code.bydev.io/frameworks/sechub-go/client"
	"github.com/spf13/viper"
)

const KeyHTTPPort = "http_port"
const KeyDebug = "debug"
const KeyAlarmEnv = "alarm_env"
const KeyLarkAlarmURL = "lark_alarm_url"
const LarkAlarmURL = "https://open.larksuite.com/open-apis/bot/v2/hook/4fd52412-f2e0-445c-b557-86648343f513"
const ImageCompress = "image.compress"
const KeyAWSRegion = "aws_region"
const KeyAWSTimeout = "aws_timeout"
const KYCS3Bucket = "kyc_bucket"
const CustomerReasonDefault = "Verification failed, please try again. If you have further questions, please contact our customer support."
const KeyWorkerNum = "consumer_worker_num"

var cfg *viper.Viper

func Load() {
	if cfg != nil {
		return
	}
	cfg = viper.New()

	// 设置选项默认值
	cfg.SetDefault(KeyHTTPPort, 8080)
	cfg.SetDefault(KeyDebug, false)
	cfg.SetDefault(KeyLarkAlarmURL, LarkAlarmURL)
	cfg.SetDefault(KeyWorkerNum, 10)
	cfg.SetDefault(KYCS3Bucket, "thanos-test.byops.io")
	cfg.SetDefault(KeyAWSTimeout, time.Second)
	cfg.SetDefault(KeyAWSRegion, "ap-southeast-1")
	err := cfg.BindEnv(KeyAWSRegion, "AWS_REGION")
	if err != nil {
		log.Fatal(err)
	}
	err = cfg.BindEnv(KeyAWSTimeout, "AWS_TIMEOUT")
	if err != nil {
		log.Fatal(err)
	}

	configName := os.Getenv(fmt.Sprintf("%s_CONFIGNAME", strings.ToUpper(meta.ProjectCode)))
	if configName == "" {
		configName = meta.ProjectCode
	}
	cfg.SetConfigName(configName)
	cfg.SetEnvPrefix(meta.ProjectCode)
	cfg.SetEnvKeyReplacer(strings.NewReplacer(".", "__"))
	cfg.AutomaticEnv()

	cfg.AddConfigPath(filepath.Dir(os.Args[0]))
	cfg.AddConfigPath(".")

	err = cfg.ReadInConfig()
	if err != nil {
		log.Fatal(err)
	}
}

func Viper() *viper.Viper {
	return cfg
}

func SetViper(vp *viper.Viper) {
	cfg = vp
}

func GetBool(s string) bool {
	return Viper().GetBool(s)
}

func GetString(s string) string {
	return Viper().GetString(s)
}

func GetStringSlice(s string) []string {
	return Viper().GetStringSlice(s)
}

func GetStringSliceComma(s string) []string {
	return strings.Split(Viper().GetString(s), ",")
}

func GetInt(s string) int {
	return Viper().GetInt(s)
}

func InDebug() bool {
	return GetBool(KeyDebug)
}

type SechubConfig struct {
	Host       string `mapstructure:"host"`
	AppName    string `mapstructure:"app_name"`
	AppSignKey string `mapstructure:"app_sign_key"`
	AppTLSCrt  string `mapstructure:"app_tls_crt"`
}

var sechubCaller *api.Sechub

func KycSechub() *api.Sechub {
	if sechubCaller == nil {
		var sechubConfig SechubConfig
		err := Viper().UnmarshalKey("access.sechub", &sechubConfig)
		if err != nil {
			return nil
		}

		if sechubConfig.Host == "" || sechubConfig.AppName == "" ||
			sechubConfig.AppSignKey == "" || sechubConfig.AppTLSCrt == "" {
			return nil
		}

		cfg := &sechub_client.Config{
			Host:       sechubConfig.Host,
			AppName:    sechubConfig.AppName,
			AppSignKey: sechubConfig.AppSignKey,
			TLSCert:    sechubConfig.AppTLSCrt,
		}
		sechubCaller = api.NewClient(cfg)
	}

	return sechubCaller
}

type ImageCompressConfig struct {
	Quality uint   `mapstructure:"quality"`
	Format  string `mapstructure:"format"`
	MinSize int    `mapstructure:"min_size"`
}

var onceImageCompressConfig sync.Once
var imgCompressConfig ImageCompressConfig

func GetImageCompressConfig() *ImageCompressConfig {
	onceImageCompressConfig.Do(func() {
		_ = Viper().UnmarshalKey(ImageCompress, &imgCompressConfig)
	})
	return &imgCompressConfig
}

var adminSechubCaller *api.Sechub

func Sechub() *api.Sechub {
	if adminSechubCaller == nil {
		var sechubConfig SechubConfig
		err := Viper().UnmarshalKey("access.sechub_admin", &sechubConfig)
		if err != nil {
			return nil
		}

		if sechubConfig.Host == "" || sechubConfig.AppName == "" ||
			sechubConfig.AppSignKey == "" || sechubConfig.AppTLSCrt == "" {
			return nil
		}

		c := &sechub_client.Config{
			Host:       sechubConfig.Host,
			AppName:    sechubConfig.AppName,
			AppSignKey: sechubConfig.AppSignKey,
			TLSCert:    sechubConfig.AppTLSCrt,
		}
		adminSechubCaller = api.NewClient(c)
	}

	return adminSechubCaller
}

type PoaAlarmConfig struct {
	CountryList []string `mapstructure:"country_list"`
	LarkURL     string   `mapstructure:"lark_url"`
	MinTimes    int      `mapstructure:"min_times"`
}

var (
	poaAlarmConfig     PoaAlarmConfig
	oncePoaAlarmConfig sync.Once
)

func GetPoaAlarmConfig() *PoaAlarmConfig {
	oncePoaAlarmConfig.Do(func() {
		_ = Viper().UnmarshalKey("poa.alarm", &poaAlarmConfig)
	})
	return &poaAlarmConfig
}

type KMSConfig struct {
	InternalKeyID  string `mapstructure:"internal_key_id"`
	InternalCipher string `mapstructure:"internal_cipher"`
}

func GetDownloadImageTimeout() time.Duration {
	return time.Duration(GetInt("common.download_image_timeout")) * time.Second
}
